package org.mtmi.ui.controls;

import org.mtmi.tuio.listeners.DragListener;
import org.mtmi.tuio.listeners.TUIODragEvent;
import org.mtmi.tuio.listeners.TUIOTapEvent;
import org.mtmi.ui.M;
import org.mtmi.ui.scenes.Scene;

/** 
 * Common part for linear slider (vertical or horizontal).
 *
 */
public abstract class AbstractSlider extends AbstractRangeValueControl
 implements DragListener 
{

	private int tapPos;
	private int delta;
	private boolean isMoving; //true when user moves the thumb
	
	public AbstractSlider( Scene scene, int flags ) {
		super( scene, flags );
	}
	
	/** create slider, use M.VERTICAL or M.HORIZONTAL in flags for direction */
	public AbstractSlider( Scene scene, int valCurrent, int valMin, int valMax, int flags ) {
		super( scene, valCurrent, valMin, valMax, flags );
	}
	
	public boolean isHorizontal() { return (getFlags() & M.VERTICAL)==0; }
	
	/**
	 * Returns the value in the slider range ([valMin, valMax]) of the given pixel position
	 * @param p pixel position of the thumb
	 * @return
	 */
	protected int getThumbValue( int p ) {
		int pmax = getPMax();
		int pmin = getPMin();
		if( isHorizontal() ) {
			//note: ca c'est bon si valMin < valMax (de gauche a droite)
			if(p <= pmin) return valMin;
			if(p >= pmax) return valMax;
		} else {
			//note: y order are reversed at screen
			if(p >= pmin) return valMin;
			if(p <= pmax) return valMax;
		}
		return valMin+((p-pmin)*(valMax-valMin))/(pmax - pmin);
	}
	
	/**
	 * Returns the absolute position of the thumb according the given value.
	 * @param value a value for the slide between valMin and valMax.
	 * @return
	 */
	protected int getThumbPosition(int value) {
		int pmax = getPMax();
		int pmin = getPMin();
		return pmin+((value-valMin)*(pmax - pmin))/(valMax-valMin);
	}

	@Override
	public void tapDown(TUIOTapEvent event) {
		if( isThumbContains( event.ex, event.ey ) ) {
			isMoving = true;
			if( isHorizontal() ) {
				tapPos = event.ex;
			} else {
				tapPos = event.ey;
			}
			int thumbPos = getThumbPosition( getValue() );
			delta = tapPos - thumbPos;
		}
	}

	@Override
	public void tapUp(TUIOTapEvent event) { isMoving=false; }

	@Override
	public void drag(TUIODragEvent event) {
		if( isMoving ) {
			int newPos = isHorizontal() ? event.ex : event.ey;
			if ((newPos - tapPos) != 0) {
				int nv = getThumbValue(newPos - delta);
				if( nv != getValue() ) {
					setValue( nv );
					tapPos = newPos;
					redraw();
					notifyValueChanged();
				}
			}
		}
	}
	

	/** @return true if the given point is inside thumb bounds */
	protected abstract boolean isThumbContains( int x, int y );
	/** @return absolute (pixel) position of thumb at value == valMin, depends on vertical/horizontal */
	protected abstract int getPMin();
	/** @return absolute (pixel) position of thumb at value == valMax, depends on vertical/horizontal */
	protected abstract int getPMax();
	
}
